package tech.summerly.weather.util

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Build
import android.os.Bundle
import androidx.core.content.systemService
import kotlinx.coroutines.experimental.CompletableDeferred
import kotlinx.coroutines.experimental.Job
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch
import org.jetbrains.anko.indeterminateProgressDialog
import tech.summerly.weather.AppContext
import tech.summerly.weather.R
import tech.summerly.weather.data.remote.AmapService
import tech.summerly.weather.model.Region

/**
 * 获取用户此时的经纬度
 */
object LocationHelper {


    private val context: Context get() = AppContext.instance


    private val listeners = ArrayList<LocationListener>()

    suspend fun currentLocation(): CompletableDeferred<Region> {
        val deferred = CompletableDeferred<Region>()
        listenLocation { position ->
            log { "定位成功 $position" }
            clearListener()
            launch(UI) {
                try {
                    val region = AmapService.getRegionByPosition1(position)
                    deferred.complete(region)
                } catch (e: Exception) {
                    deferred.completeExceptionally(e)
                }
            }
        }
        return deferred
    }

    fun listenLocation(onLocation: (position: Position) -> Unit) {
        val locationManager = context.systemService<LocationManager>()
        val isLocationAvailable = with(locationManager) {
            isProviderEnabled(LocationManager.GPS_PROVIDER) || isProviderEnabled(LocationManager.NETWORK_PROVIDER)
        }
        if (!isLocationAvailable) {
            dialogForLocation()
            log { "定位功能不可用" }
            return
        }

        val locationListener = object : LocationListener {
            override fun onLocationChanged(location: Location) {
                locationManager.removeUpdates(this)
                log { "实时定位成功" }
                onLocation(Position(location.longitude, location.latitude))
            }

            override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {

            }

            override fun onProviderEnabled(provider: String?) {

            }

            override fun onProviderDisabled(provider: String?) {

            }

        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
                && context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            //request permission
            return
        }
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000L, 500f, locationListener)
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000L, 500f, locationListener)
        listeners.add(locationListener)
        try {
            val location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
                    ?: locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
                    ?: return
            return onLocation(Position(location.longitude, location.latitude))
        } catch (e: Exception) {
            log { e.printStackTrace() }
        }
    }


    fun clearListener() {
        val locationManager = context.systemService<LocationManager>()
        listeners.forEach {
            locationManager.removeUpdates(it)
        }
    }

    private fun dialogForLocation() {

//        val alertDialog = AlertDialog.Builder(ContextThemeWrapper(context, R.style.Theme_AppCompat_Dialog_Alert))
//                .setMessage("定位服务不可用，需要打开定位开关才能使用定位功能。")
//                .setPositiveButton("打开") { dialog, _ ->
//                    //todo goto system service
//                    dialog.dismiss()
//                }
//                .setNegativeButton("算了") { dialog, _ ->
//                    dialog.dismiss()
//                }
//                .create()
//        alertDialog.show()
    }

}

suspend fun Context.getLocationWithDialog(): Region? {
    val job = Job()
    val dialog = indeterminateProgressDialog(message = R.string.locationning) {
        setOnDismissListener {
            job.cancel()
        }
    }
    var region: Region? = null
    launch(UI, parent = job) {
        try {
            region = LocationHelper.currentLocation().await()
            log { region }
        } catch (e: Exception) {
            log { "出错 : ${e.message}" }
        } finally {
            dialog.dismiss()
        }
    }.join()
    return region
}
